#include "map.h"
#include <osgDB/FileNameUtils>
#include "datatypedefine.h"

namespace CoreBase
{
	const QString Map::MAP_FILE_EXTENSION(".jcyj");
	Map::Map(const QString& type, const QString& name): _modified(true) , _name(name),_mapType(type)
	{
		setFileName(_name);
		//mEventManager = new MapGameEvents(*this);
		_presetCameras.resize(10);
	}

	Map::~Map()
	{
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator iter = _actorMap.begin();
		for(;iter!=_actorMap.end();++iter)
		{
			iter.value()->setBelongMap(NULL);
			if(iter.value()!=NULL && iter.value()->isInstanceOf(CLASS_DEVICE))
			{
				iter.value() = NULL;
			}
		}
	}

	ActorBase* Map::getActorById(const QString& id)
	{
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator i = _actorMap.find(id);
		if (i != _actorMap.end())
		{
			return i.value().get();
		}
		return NULL;
	}

	ActorBase* Map::getActorByName(const QString& name)
	{
		QMap<QString,ActorBase*>::iterator i = _resourceDevNameToActor.find(name);
		if (i != _resourceDevNameToActor.end())
		{
			return i.value();
		}
		return NULL;
	}

	const ActorBase* Map::getActorById(const QString& id) const
	{
		QMap<QString, osg::ref_ptr<ActorBase>>::const_iterator i = _actorMap.find(id);
		if (i != _actorMap.end())
		{
			return i.value().get();
		}
		return NULL;
	}

	void Map::setFileName(const QString& newfilename)
	{
		_fileName = newfilename;
		if (_fileName == "")
			return;
		//if (osgDB::getFileExtension(_fileName).empty())
		//{
		//   _fileName += MAP_FILE_EXTENSION;
		//}
	}

	void Map::addActor(ActorBase& actor)
	{
		QString actorid = actor.getId();
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator i = _actorMap.find(actor.getId());
		if (i == _actorMap.end())
		{
			_actorMap.insert(actorid,osg::ref_ptr<ActorBase>(&actor));
			if(!_resourceDevNameToActor.contains(actor.getName()))
				_resourceDevNameToActor.insert(actor.getName(),&actor);
			_modified = true;
			actor.setBelongMap(this);
			if(_mapType == MAP_TYPE_RESOURCEMAP)
				actor.addToMapEnd(this);
		}
	}

	bool Map::removeActor(ActorBase& actor)
	{
		//This needs to be faster.
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator i = _actorMap.find(actor.getId());
		if (i != _actorMap.end())
		{
			_modified = true;
			if(_mapType == MAP_TYPE_RESOURCEMAP)
				actor.removeFromMapEnd(this);
			_actorMap.erase(i);
			return true;
		}
		return false;
	}


	void Map::clearActors()
	{
		_actorMap.clear();
	}

	void Map::clearModified()
	{
		_modified = false;
		_savedName = _name;
	}

	void Map::setEnvironmentActor(ActorBase *envactor)
	{
		if (envactor == NULL)
		{
			removeActor(*_envActor);
			_envActor = NULL;
			return;
		}
		//IEnvironmentActor *ea = dynamic_cast<IEnvironmentActor*>(envactor->GetActor());
		//if (ea == NULL)
		//{
		//}
		//_envActor = envactor;
		addActor(*_envActor);
	}

	Map::PresetCameraData Map::getPresetCameraData(int index)
	{
		if (index < 0 || index >= (int)_presetCameras.size())
		{
			return PresetCameraData();
		}
		return _presetCameras[index];
	}

	void Map::setPresetCameraData(int index, Map::PresetCameraData presetdata)
	{
		if (index < 0 || index >= (int)_presetCameras.size())
		{
			return;
		}
		_presetCameras[index] = presetdata;
	}

	const QString& Map::getName() const
	{
		return _name;
	}

	const QString& Map::getSavedName() const
	{
		return _savedName;
	}

	void Map::setName(const QString& newname)
	{
		_modified = true; _name = newname;
	}

	const QString& Map::getFileName() const
	{
		return _fileName;
	}

	const QString& Map::getDescription() const
	{
		return _description;
	}

	void Map::setDescription(const QString& newdescription)
	{
		_modified = true;
		_description = newdescription;
	}

	const QString& Map::getAuthor() const
	{
		return _author;
	}

	void Map::setAuthor(const QString& newauthor)
	{
		_modified = true;
		_author = newauthor;
	}

	void Map::setReferenceUnitConversion(const QString& ruc)
	{
		_referenceUnitConversion = ruc;
	}

	QString Map::getReferenceUnitConversion()
	{
		return _referenceUnitConversion;
	}

	QString Map::getResource() const
	{
		QString resource = "";
		for(int i=0;i<_resourceList.size();++i)
		{
			resource = resource+","+_resourceList.at(i);
		}
		return resource;
	}

	void Map::setResource(const QString& resource)
	{
		_modified = true;
		_resourceList.clear();
		_resourceList = resource.split(',',QString::SkipEmptyParts);
	}

	const QString& Map::getCreateDateTime() const
	{
		return _createDateTime;
	}

	void Map::setCreateDateTime(const QString& newcreatedatetime)
	{
		_modified = true;
		_createDateTime = newcreatedatetime;
	}

	const QMap<QString, osg::ref_ptr<ActorBase>>& Map::getAllActors() const
	{
		return _actorMap;
	}

	void Map::getAllActors(QVector<osg::ref_ptr<ActorBase> >& container)
	{
		container.clear();
		QMap<QString, osg::ref_ptr<ActorBase>>::Iterator iter = _actorMap.begin();
		for(;iter!=_actorMap.end();++iter)
		{
			container.push_back(iter.value());
		}
	}

	bool Map::isModified() const
	{
		return _modified;
	}

	void Map::setModified(bool val)
	{
		_modified = val;
	}

	void Map::addResource(const QString& name)
	{
		if(!_resourceList.contains(name))
			_resourceList.push_back(name);
	}

	bool Map::removeResource(const QString& name)
	{
		if(_resourceList.contains(name))
			_resourceList.removeOne(name);
		return true;
	}

	void Map::resourceRename(const QString& oldname,const QString& newname)
	{
		removeResource(oldname);
		addResource(newname);
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator iter = _actorMap.begin();
		for(;iter!=_actorMap.end();++iter)
		{
			if(iter.value()->isInstanceOf(CLASS_DEVICE))
			{
				QString devoldname = iter.value()->getName();
				if(devoldname.startsWith(oldname))
				{
					devoldname.replace(oldname,newname);
				}
			}
		}
	}

	void Map::updateActorName(const QString& oldname,const QString& newname)
	{
		QMap<QString, osg::ref_ptr<ActorBase>>::iterator iter = _actorMap.begin();
		for(;iter!=_actorMap.end();++iter)
		{
			if(iter.value()->isInstanceOf(CLASS_DEVICE))
			{
				QString devoldname = iter.value()->getName();
				if(devoldname == oldname)
				{
					iter.value()->setName(newname);
				}
			}
		}
	}

	const QStringList& Map::getAllResource() const
	{
		return _resourceList;
	}

	bool Map::hasResource(const QString& name) const
	{
		return  _resourceList.contains(name);
	}

	ActorBase* Map::getEnvironmentActor()
	{
		return _envActor.get();
	}

	const ActorBase* Map::getEnvironmentActor() const
	{
		return _envActor.get();
	}

	void Map::setSavedName(const QString& newsavedname)
	{
		_savedName = newsavedname;
	}
}
